package no.hib.mod250.chat.client.view;

import java.util.LinkedList;

import no.hib.mod250.chat.client.controller.ChatController;
import no.hib.mod250.chat.client.controller.ChatController.DoInitializeTask;
import no.hib.mod250.chat.client.controller.ChatController.DoMessageDeleteTask;
import no.hib.mod250.chat.client.controller.ChatController.DoMessageNewTask;
import no.hib.mod250.chat.client.controller.ChatController.DoUpdateTask;
import no.hib.mod250.chat.client.controller.Controller.Task;
import no.hib.mod250.chat.client.service.ChatService;
import no.hib.mod250.chat.client.util.ObjectWithEvent;
import no.hib.mod250.chat.client.util.R;

import org.adamtacy.client.ui.effects.events.EffectCompletedEvent;
import org.adamtacy.client.ui.effects.events.EffectCompletedHandler;
import org.adamtacy.client.ui.effects.impl.Fade;
import org.adamtacy.client.ui.effects.transitionsphysics.LinearTransitionPhysics;

import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;

public class StatusView extends View implements View.StatusObserver,
		View.DataObserver {

	// CLASSES

	protected class StatusQueue {

		private LinkedList<String> queue = new LinkedList<String>();

		public void post(String status) {
			queue.add(status);

			if (queue.size() == 1) {
				executeHead();
			}
		}

		protected void executeHead() {
			if (!queue.isEmpty()) {
				doShowStatus(queue.getFirst());
			}
		}

		protected void executeNext() {
			queue.removeFirst();
			executeHead();
		}

		protected void doShowStatus(String status) {
			Fade fade = new Fade();
			fade.setDuration(1.0);
			fade.setTransitionType(new LinearTransitionPhysics());
			fade.setEffectElement(lblStatusText.getElement());

			lblStatusText.setText(status);
			fade.addEffectCompletedHandler(new EffectCompletedHandler() {

				@Override
				public void onEffectCompleted(EffectCompletedEvent event) {
					doRemoveStatus();
				}
			});
			fade.play(1.0, 0.0);
		}

		protected void doRemoveStatus() {
			Fade fade = new Fade();
			fade.setDuration(1.0);
			fade.setTransitionType(new LinearTransitionPhysics());
			fade.setEffectElement(lblStatusText.getElement());
			fade.addEffectCompletedHandler(new EffectCompletedHandler() {

				@Override
				public void onEffectCompleted(EffectCompletedEvent event) {
					executeNext();
				}
			});
			fade.play(0.0, 1.0);
		}

	}

	// /CLASSES

	// VARIABLES

	private FlowPanel panel = new FlowPanel();
	private Image imgLoader = new Image(R.Image.loader);
	private Label lblLoaderText = new Label();
	private Label lblStatusText = new Label();
	private Grid grdStatusBar = new Grid(1, 3);
	private StatusQueue statusQueue = new StatusQueue();
	private Label serverError = new Label("Server error!");

	// /VARIABLES

	// CONSTRUCTOR

	public StatusView(final ChatController controller) {
		super(controller);

		controller.addDataObserver(this);
		controller.addStatusObserver(this);

		initWidget(panel);

		doDraw();
		doEvent();
	}

	// /CONSTRUCTOR

	// FUNCTIONS

	// ... DO

	@Override
	protected void doDraw() {
		panel.add(grdStatusBar);
		
		lblLoaderText.setVisible(false);
		lblStatusText.setVisible(true);
		lblStatusText.setStyleName("opacity_none");
		imgLoader.setVisible(false);

		grdStatusBar.setStyleName(R.Class.statusBar);
		grdStatusBar.setWidget(0, 0, imgLoader);
		grdStatusBar.setWidget(0, 1, lblLoaderText);
		grdStatusBar.setWidget(0, 2, lblStatusText);

		serverError.setVisible(false);
		serverError.addStyleName("server-error");
		serverError.setText("Server Disconnected");
		panel.add(serverError);
	}

	private void doEvent() {
		getController().getTimerUpdateEnabled().addListener(
				new ObjectWithEvent.Listener<Boolean>() {

					@Override
					public void onChanged(Boolean value) {
						statusQueue.post(value ? "Update timer enabled"
								: "Update timer disabled");
					}

				});

		getController().getUpdateWhileBusy().addListener(
				new ObjectWithEvent.Listener<Boolean>() {

					@Override
					public void onChanged(Boolean value) {
						statusQueue.post(value ? "Update while buys enabled"
								: "Update while busy disabled");
					}

				});
	}

	// ... /DO

	// ... ON

	// ... ... DATA

	@Override
	public void onDataResult(ChatService.Result result) {

	}

	// ... ... /DATA

	// ... ... STATUS

	@Override
	public void onStatusServerCameBack() {
		serverError.setVisible(false);
	}

	@Override
	public void onStatusServerWentAway() {
		serverError.setVisible(true);
	}

	@Override
	public void onStatusTaskFinished(Task task) {
		// // Initialize task
		// if (task instanceof DoInitializeTask) {
		// lblLoaderText.setText("Finished initialize task");
		// }
		// // Send message
		// else if (task instanceof DoMessageNewTask) {
		// lblLoaderText.setText("Finished sending message task");
		// }
		// // Update
		// else if (task instanceof DoUpdateTask) {
		// lblLoaderText.setText("Finished updating task");
		// }
		lblLoaderText.setVisible(false);
		imgLoader.setVisible(false);
	}

	@Override
	public void onStatusTaskStarted(Task task) {
		// Initialize task
		if (task instanceof DoInitializeTask) {
			lblLoaderText.setText("Starting initialize task");
		}
		// Send message
		else if (task instanceof DoMessageNewTask) {
			lblLoaderText.setText("Sending message task");
		}
		// Update
		else if (task instanceof DoUpdateTask) {
			lblLoaderText.setText("Updating task");
		}
		// Delete message
		else if (task instanceof DoMessageDeleteTask) {
			lblLoaderText.setText("Deleting task");
		}
		
		lblLoaderText.setVisible(true);
		imgLoader.setVisible(true);
	}

	// ... ... /STATUS

	// ... /ON

	// /FUNCTIONS

}
